package com.xuzz.study.spring.autowired;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @description:
 * @author: xuzz
 * @create: 2020-02-27 16:02
 */
@Configuration
public class AutowiredConfiguration {

    //autowired加上LoadBalanced，标识只注入带有LoadBalanced的bean
    //LoadBalanced是Qualifier的实现。效果类似于
    // @Autowired  @Qualifier

    //这个也就是Ribbon中RestTemplate负载均衡的原理之一
    @LoadBalanced
    @Autowired(required = false)
    private List<MockRestTemplate> restTemplates = Collections.emptyList();


    //这个打上@LoadBalaced注解
    @Bean
    @LoadBalanced
    public MockRestTemplate restTemplate()
    {
        return new MockRestTemplate();
    }

    public void get()
    {
        for (MockRestTemplate restTemplate : AutowiredConfiguration.this.restTemplates)
        {
            restTemplate.get();
        }
    }

    //SmartInitializingSingleton是一个函数式接口，所以可以lamdba返回
    @Bean
    SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(final ObjectProvider<List<MockRestTemplateCustomizer>> restTemplateCustomizers) {
        // ()，标识没有参数。而SmartInitializingSingleton的唯一方法afterSingletonsInstantiated确实是没参数的
        return ()->restTemplateCustomizers.ifAvailable( customizers-> {
            for (MockRestTemplate restTemplate : AutowiredConfiguration.this.restTemplates) {
                for (MockRestTemplateCustomizer customizer : customizers) {
                    customizer.customize(restTemplate);
                }
            }
        });
    }

    @Bean
    public LoadBalanceInterceptor loadBalancerInterceptor() {
        return new LoadBalanceInterceptor();
    }

    //MockRestTemplateCustomizer是一个函数式接口，所以可以lamdba返回
    @Bean
    public MockRestTemplateCustomizer restTemplateCustomizer(final LoadBalanceInterceptor loadBalancerInterceptor) {
        return restTemplate -> {
            List<MockRestTemplate.Interceptor> list = new ArrayList<>(restTemplate.getInterceptors());
            list.add(loadBalancerInterceptor);
            restTemplate.setInterceptors(list);
        };
    }
}
